package com.marketlive.entity;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/*
(C) Copyright MarketLive. 2006. All rights reserved.
MarketLive is a trademark of MarketLive, Inc.
Warning: This computer program is protected by copyright law and international treaties.
Unauthorized reproduction or distribution of this program, or any portion of it, may result
in severe civil and criminal penalties, and will be prosecuted to the maximum extent
possible under the law.
*/


import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;

/**
 * Maps {@link java.lang.Double} to a DOUBLE field in the database.
 */
public class DoubleType implements UserType {

    /** The default value for <code>DoubleType</code>s. */
    public static final double DEFAULT_VALUE = 0.0;

    /** The types that <code>DoubleType</code> maps to. */
    public static final int[] SQL_TYPES = new int[]{java.sql.Types.DOUBLE};

    /** Logger for this class. */
    private static Log log = LogFactory.getLog(DoubleType.class);

    /**
     * Return the SQL type codes for the columns mapped by this type.
     * The codes are defined on java.sql.Types.
     * @return a one-element array containing the value java.sql.Types.DOUBLE
     * @see java.sql.Types
     */
    public int[] sqlTypes() {
        return SQL_TYPES;
    }

    /**
     * Returns the class that is returned by <code>nullSafeGet()</code>.
     *
     * @return the <code>Double</code> class
     */
    public Class returnedClass() {
        return Double.class;
    }

    /**
     * Compares two instances of the class mapped by this type for persistence equality.
     * If the two instances are null or the same, returns true. If one instance is null
     * and the other is not, returns false. If none of these conditions apply, delegates
     * to <code>x.equals(y)</code>.
     *
     * @param x first object to compare
     * @param y second object to compare
     * @return true if the two objects represent the same entity
     * @throws org.hibernate.HibernateException if the operation fails
     */
    public boolean equals(Object x, Object y) throws HibernateException {
        if (x == y) {
            return true;
        } else if (x == null || y == null) {
            return false;
        } else {
            return x.equals(y);
        }
    }

    /**
     * Retrieves a <code>Double</code> from a JDBC ResultSet.
     *
     * @param rs the result set to examine
     * @param names an array of column names. Only the first element in the array is used.
     * @param obj not used
     * @return a <code>Double</code> from the given result set, or null if none was found
     * @throws org.hibernate.HibernateException if an error occurs
     * @throws java.sql.SQLException if an error occurs
     */
    public Object nullSafeGet(ResultSet rs, String[] names, Object obj)
            throws HibernateException, SQLException {

        Double value = (Double) Hibernate.DOUBLE.nullSafeGet(rs, names[0]);

        if (value == null) {
            return new Double(DEFAULT_VALUE);
        } else {
            return value;
        }
    }

    /**
     * Sets the given value as a query parameter on the given statement.
     *
     * @param ps the statement to set the value for
     * @param obj the value to set
     * @param index the index in the statement to which the value corresponds
     * @throws org.hibernate.HibernateException if an error occurs
     * @throws java.sql.SQLException if an error occurs
     * @see org.hibernate.UserType
     */
    public void nullSafeSet(PreparedStatement ps, Object obj, int index)
            throws HibernateException, SQLException {

        if (obj == null) {
            obj = new Double(DEFAULT_VALUE);
        }

        Hibernate.DOUBLE.nullSafeSet(ps, obj, index);
    }

    /**
     * Returns a reference to the original object.
     *
     * @param obj the object to copy
     * @return a reference to the given object
     * @throws HibernateException if an error occurs
     */
    public Object deepCopy(Object obj) throws HibernateException {
        return obj;
    }

    /**
     * Returns whether this object can be modified. <code>DoubleType</code> is immutable.
     * @return false
     */
    public boolean isMutable() {
        return false;
    }

    /**
     * Returns a hash code for the given object that is consistent with persistence equality.
     *
     * @param pDouble the <code>Double</code> for which to generate a hash code
     * @return the hash code for the given <code>Double</code>
     * @throws HibernateException if an error occurs
     * @throws NullPointerException if <code>pDouble</code> is null
     */
    public int hashCode(Object pDouble) throws HibernateException {
        return pDouble.hashCode();
    }

    /**
     * Transforms the given object into a cacheable representation.
     * Casts the given object to <code>Serializable</code>.
     *
     * @param pDouble the object to transform
     * @return a cacheable form of the given double
     * @throws HibernateException if an error occurs
     */
    public Serializable disassemble(Object pDouble) throws HibernateException {
        return (Serializable) pDouble;
    }

    /**
     * Reconstructs an object from its cacheable representation.
     * @param pCached the object to assemble
     * @param pOwner the owner. Not used.
     * @return a reference to <code>pCached</code>
     * @throws HibernateException if an error occurs
     */
    public Object assemble(Serializable pCached, Object pOwner) throws HibernateException {
        return pCached;
    }

    /**
     * Returns the original object.
     *
     * @param pOriginal the original object to merge into the target
     * @param pTarget the target object. Not used.
     * @param pOwner the owner of the object. Not used.
     * @return a reference to <code>pOriginal</code>
     * @throws HibernateException if an error occurs
     */
    public Object replace(Object pOriginal, Object pTarget, Object pOwner) throws HibernateException {
        return pOriginal;
    }

}
